
package compiladorP2.gui;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import maquina_virtualP2.gui.MaquinaVirtualView;
import util.Util;

import compiladorP2.compilador.Error;
import compiladorP2.compilador.sintactico.Parser;

/**
 * Ventana principal del compilador.
 * @author Miguel Angel Diaz Calvo
 */
public class CompiladorView extends javax.swing.JFrame {
	
    private static final long serialVersionUID = 1L;
	
	private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextArea jTextArea1;
    private javax.swing.JTextArea jTextArea2;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    
    private CompiladorManualBox manualBox;
    private CompiladorAboutBox aboutBox;
    private BufferedReader ficheroFuente;
    private Parser parser;
    
    private String ultimaRuta;
    private String consola;
    
    private MaquinaVirtualView mv;


    /** Creates new form CompiladorView */
    public CompiladorView() {
        mv = null;
        initComponents();
        ultimaRuta = "";
        consola = "";
    }
    
    /** Creates new form CompiladorView */
    public CompiladorView(MaquinaVirtualView mv) {
        this.mv = mv;
        initComponents();
        ultimaRuta = "";
        consola = "";
    }

    private void abrirArchivo(java.awt.event.ActionEvent evt) {
		JFileChooser jFileChooser= new JFileChooser();
		if (ultimaRuta.equals(""))
			jFileChooser.setCurrentDirectory(new File("."));
		else
			jFileChooser.setCurrentDirectory(new File(ultimaRuta));
		jFileChooser.setMultiSelectionEnabled(false);
		jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
		jFileChooser.showOpenDialog(this);
		try {
			ultimaRuta = jFileChooser.getSelectedFile().getParent();
			String archivoSalida = jFileChooser.getSelectedFile().getName();
			archivoSalida = archivoSalida.substring(0, archivoSalida.lastIndexOf(".")) + ".o";
			jTextField1.setText(archivoSalida);
			File fich= new File(jFileChooser.getSelectedFile().getPath());
			FileReader fichero;
			try{
				fichero = new FileReader(fich);
				ficheroFuente = new BufferedReader(fichero);			
				try {				
					if (mv == null)
						jTextArea1.setText(" //DEBUG programa para compilar:\n\n");
					else
						jTextArea1.setText("");
					FileReader fichero2 = new FileReader(fich);
					BufferedReader entrada = new BufferedReader(fichero2);
					String linea = null;
					int index = 1;
					while ((linea = entrada.readLine()) != null){
					String leido = linea.trim();
						if (mv == null)
							jTextArea1.setText(jTextArea1.getText()+"\n"+ index++ + "# " + leido);
						else
							jTextArea1.setText(jTextArea1.getText()+"\n"+leido);
					}
					consola += "Archivo abierto: " + fich + "\n";
					setTitle("Compilador 2.0 - " + fich.getName());
					jTextArea2.setText(consola);
				}
				catch (IOException ex) {
					Error e = new Error("Se produjo un error leyendo el fichero");
					e.setTipo(Error.SOLOMOTIVO);
					throw e;
				}				
			}
			catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(this, "Archivo no encontrado", "Error", JOptionPane.ERROR_MESSAGE);
				ficheroFuente = null;
				jTextArea1.setText("//c\u00f3digo para compilar");
			}   
			catch (Error e){
				consola += e.getMessage() + "\n";
				jTextArea2.setText(consola);
			}
		} catch(NullPointerException e){
			// Se ha pulsado el boton cancelar, no se hace nada
		}
    }

    private void compilar(java.awt.event.ActionEvent evt) {
    	if (jTextArea1.getText().compareTo("")==0){
    		consola += "No hay nada que compilar.\n";
    		jTextArea2.setText(consola);
    		return;
    	}    		
		long time = System.currentTimeMillis();
		jButton2.setEnabled(false);
		FileWriter fw;
		PrintWriter salArch;
		BufferedWriter bw;
		try {
			String ruta;
			if (ultimaRuta.compareTo("")==0)
				ruta = Util.rutaTrabajo() + File.separator + jTextField1.getText();
			else
				ruta = ultimaRuta + File.separator + jTextField1.getText();
			// Se pasa el texto del editor a un archivo
			fw = new FileWriter(ruta);
			bw = new BufferedWriter(fw);
			salArch = new PrintWriter(bw);
			for (int i=0; i<jTextArea1.getLineCount(); i++){
				String linea = jTextArea1.getText().substring(jTextArea1.getLineStartOffset(i), jTextArea1.getLineEndOffset(i));
				if (linea.toCharArray()[0] != 10)
					salArch.println(linea);
			}
			salArch.close();
			ficheroFuente = new BufferedReader(new FileReader(new File(ruta)));
			// Compilacion
			try{
				parser = new Parser(ficheroFuente);
	
				parser.setAtributos(parser.Prog());
	
				if ( !parser.getTextoError().equals("") ) {		//Se produjo un error	
					consola += "ERROR " + parser.getTextoError() + "\n\n";
					jTextArea2.setText(consola);
				} 
				else { // Si no se produjeron errores 
	
					//Se setea el codigo del parser con el de los atributos resultante
					parser.setCodigo( parser.getAtributos().getCodigo() );
	
					if (mv == null)
						jTextArea1.setText(jTextArea1.getText() + "\n\n//----\n //DEBUG: c\u00f3digo objeto:\n//---- \n\n");
					try {
						fw = new FileWriter(ultimaRuta + File.separator + jTextField1.getText());
						bw = new BufferedWriter(fw);
						salArch = new PrintWriter(bw);
						for (int i = 0; i< parser.getCodigo().length(); i++){
							if (parser.getCodigo().toCharArray()[i] != ';'  ){
								if (mv == null)
									jTextArea1.setText(jTextArea1.getText() + parser.getCodigo().toCharArray()[i] );
								salArch.print( parser.getCodigo().toCharArray()[i]  ) ;
							} else {
								if (mv == null)
									jTextArea1.setText(jTextArea1.getText() + parser.getCodigo().toCharArray()[i] + "\n");
								salArch.println( parser.getCodigo().toCharArray()[i]  ) ;
							}
						}
						salArch.close();
						if (mv != null){
							mv.abrirArchivo(ultimaRuta + File.separator + jTextField1.getText());
							mv.setVisible(true);
						}
						//Se informa del exito de la compilacion
						consola += "Compilaci\u00f3n exitosa, tiempo de compilaci\u00f3n: " + (System.currentTimeMillis() -  time) + " ms.\n";
						consola += "Salida guardada en: " + ultimaRuta + File.separator + jTextField1.getText() + "\n\n";
						jTextArea2.setText(consola);
					} catch (IOException e1) {
						consola += "Se produjo un error al leer el archivo.\n\n";
						jTextArea2.setText(consola);
					}
				}
				ficheroFuente = null;
			} catch(Error error){
				consola += error.getMessage() + "\n\n";
				jTextArea2.setText(consola);
			}
		} catch (Exception e) {
		}
		jButton2.setEnabled(true);
    }
    
    private void showManualBox(java.awt.event.ActionEvent evt) {
        if (manualBox == null) {
            manualBox = new CompiladorManualBox(this, true);
            manualBox.setLocationRelativeTo(this);
        }
        manualBox.setVisible(true);
    }

    private void showAboutBox(java.awt.event.ActionEvent evt) {
    	if (aboutBox == null) {
            aboutBox = new CompiladorAboutBox(this, true);
            aboutBox.setLocationRelativeTo(this);
        }
        aboutBox.setVisible(true);
    }

    /** 
     * This method is called from within the constructor to
     * initialize the form.
     */
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTextArea1 = new javax.swing.JTextArea();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea2 = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jButton1 = new javax.swing.JButton();
        jTextField1 = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jButton2 = new javax.swing.JButton();
        jLabel4 = new javax.swing.JLabel();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
        javax.swing.JMenuItem newMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setIconImage(new javax.swing.ImageIcon(util.Util.rutaTrabajo() + File.separator + "resources" + File.separator + "logo_small.png").getImage());

        setMinimumSize(new java.awt.Dimension(575, 485));
        setTitle("Compilador 2.0 - Grupo 6");
        setLocationRelativeTo(null);
        
        jTextArea1.setColumns(20);
        jTextArea1.setRows(5);
        jTextArea1.setToolTipText("Contenido del programa en c\u00f3digo fuente (EDITABLE)");
        jScrollPane1.setViewportView(jTextArea1);
        if (mv == null)
        	jTextArea1.setEditable(false);

        jTextArea2.setColumns(20);
        jTextArea2.setRows(5);
        jTextArea2.setToolTipText("Informaci\u00f3n sobre la compilaci\u00f3n");
        jScrollPane2.setViewportView(jTextArea2);
        jTextArea2.setEditable(false);

        jLabel1.setText("Programa fuente:");

        jLabel2.setText("Consola del compilador:");

        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abrirArchivo(evt);
            }
        });
	    jButton1.setText("Abrir archivo fuente");
	    jButton1.setToolTipText("Permite cargar un archivo");
	
	    jTextField1.setText("salida.o");
	    jTextField1.setToolTipText("Nombre del archivo de salida");
	
	    jLabel3.setText("Archivo de salida:");
	
	    jButton2.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            compilar(evt);
	        }
	    });
	    jButton2.setText("Compilar y lanzar MV");
	    jButton2.setToolTipText("Compila y lanza la Maquina Virtual si no ha habido errores");
	    jButton2.setPreferredSize(new java.awt.Dimension(129, 23));
	    
	    jLabel4.setIcon(new javax.swing.ImageIcon(util.Util.rutaTrabajo()+File.separator+"resources"+File.separator+"logo_small.png"));
	
	    javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(mainPanel);
	    mainPanel.setLayout(mainPanelLayout);
	    mainPanelLayout.setHorizontalGroup(
	        mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	        .addGroup(mainPanelLayout.createSequentialGroup()
	            .addContainerGap()
	            .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
	                    .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE)
	                    .addGap(6, 6, 6)
	                    .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
	                        .addGroup(mainPanelLayout.createSequentialGroup()
	                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	                            .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
	                                .addComponent(jButton2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
	                                .addComponent(jTextField1, javax.swing.GroupLayout.Alignment.TRAILING)
	                                .addComponent(jLabel3)
	                                .addComponent(jButton1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 158, javax.swing.GroupLayout.PREFERRED_SIZE)))
	                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, mainPanelLayout.createSequentialGroup()
	                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
	                            .addComponent(jLabel4)
	                            .addGap(18, 18, 18))))
	                .addComponent(jLabel1)
	                .addComponent(jLabel2)
	                .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 578, Short.MAX_VALUE))
	            .addContainerGap())
	    );
	    mainPanelLayout.setVerticalGroup(
	        mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	        .addGroup(mainPanelLayout.createSequentialGroup()
	            .addContainerGap()
	            .addComponent(jLabel1)
	            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	            .addGroup(mainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	                .addGroup(mainPanelLayout.createSequentialGroup()
	                    .addComponent(jButton1)
	                    .addGap(26, 26, 26)
	                    .addComponent(jLabel3)
	                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
	                    .addGap(38, 38, 38)
	                    .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
	                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 39, Short.MAX_VALUE)
	                    .addComponent(jLabel4))
	                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE))
	            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	            .addComponent(jLabel2)
	            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
	            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE)
	            .addContainerGap())
	    );
	
	    fileMenu.setText("Archivo");
	
	    newMenuItem.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            jTextArea1.setText("");
	            consola += "Archivo nuevo.\n\n";
	            jTextArea2.setText(consola);
	            jTextField1.setText("salida.o");
	            ultimaRuta = "";
	        }
	    });
	    newMenuItem.setText("Nuevo");
	    fileMenu.add(newMenuItem);
	
	    jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            abrirArchivo(evt);
	        }
	    });
	    jMenuItem2.setText("Abrir");
	    fileMenu.add(jMenuItem2);
	
	    exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            dispose();
	        }
	    });
	    exitMenuItem.setText("Salir");
	    fileMenu.add(exitMenuItem);
	
	    menuBar.add(fileMenu);
	
	    helpMenu.setText("Ayuda");
	
	    jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            showManualBox(evt);
	        }
	    });
	    jMenuItem1.setText("Manual");
	    helpMenu.add(jMenuItem1);
	
	    aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
	        public void actionPerformed(java.awt.event.ActionEvent evt) {
	            showAboutBox(evt);
	        }
	    });
	    aboutMenuItem.setText("Acerca de");
	    helpMenu.add(aboutMenuItem);
	
	    menuBar.add(helpMenu);
	
	    setJMenuBar(menuBar);
	
	    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
	    getContentPane().setLayout(layout);
	    layout.setHorizontalGroup(
	        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	        .addGap(0, 598, Short.MAX_VALUE)
	        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	            .addGroup(layout.createSequentialGroup()
	                .addGap(0, 0, 0)
	                .addComponent(mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
	                .addGap(0, 0, 0)))
	    );
	    layout.setVerticalGroup(
	        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	        .addGap(0, 424, Short.MAX_VALUE)
	        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
	            .addGroup(layout.createSequentialGroup()
	                .addGap(0, 0, 0)
	                .addComponent(mainPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 424, Short.MAX_VALUE)
	                .addGap(0, 0, 0)))
	    );

	    pack();
    }                      
	
}
